package com.imyuanma.qingyun.lowcode.service.impl;

import com.imyuanma.qingyun.common.util.CollectionUtil;
import com.imyuanma.qingyun.common.util.StringUtil;
import com.imyuanma.qingyun.interfaces.common.model.enums.EYesOrNoEnum;
import com.imyuanma.qingyun.interfaces.monitor.annotation.Trace;
import com.imyuanma.qingyun.lowcode.dao.ILcpDbDao;
import com.imyuanma.qingyun.lowcode.model.data.LcpDbColumnDO;
import com.imyuanma.qingyun.lowcode.model.data.LcpDbTableDO;
import com.imyuanma.qingyun.lowcode.model.enums.ELcpColumnTypeEnum;
import com.imyuanma.qingyun.lowcode.model.vo.LcpDbColumnVO;
import com.imyuanma.qingyun.lowcode.model.vo.LcpDbTableDetailVO;
import com.imyuanma.qingyun.lowcode.service.ILcpDbService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 数据库操作服务
 *
 * @author wangjy
 * @date 2022/05/04 15:30:49
 */
@Slf4j
@Service
public class LcpDbServiceImpl implements ILcpDbService {
    /**
     * DB操作
     */
    @Autowired
    private ILcpDbDao dbDao;

    /**
     * 查询数据库所有表
     *
     * @return
     */
    @Override
    public List<LcpDbTableDO> getTableList() {
        return dbDao.getTableList();
    }

    /**
     * 根据表名查询表信息
     *
     * @param tableName 表名
     * @return
     */
    @Override
    public LcpDbTableDO getTableByTableName(String tableName) {
        return dbDao.getTableByTableName(tableName);
    }

    /**
     * 根据表名查询字段信息
     *
     * @param tableName 表名
     * @return
     */
    @Override
    public List<LcpDbColumnDO> getColumnListByTableName(String tableName) {
        return dbDao.getColumnListByTableName(tableName);
    }

    /**
     * 修改字段
     *
     * @param columnVO
     */
    @Trace("修改字段")
    @Override
    public void modifyDbColumn(LcpDbColumnVO columnVO) {
        ELcpColumnTypeEnum typeEnum = ELcpColumnTypeEnum.of(columnVO.getDataType());
        String sql = String.format("alter table %s modify column %s %s%s %s %s comment '%s'",
                columnVO.getTableName(),
                columnVO.getColumnName(),
                columnVO.getDataType(),
                columnVO.getLength() == null ? "" : "(" + columnVO.getLength() + ")",
                EYesOrNoEnum.YES.getCode().equals(columnVO.getNotNull()) ? "not null" : "",
                StringUtil.isNotBlank(columnVO.getColumnDefault()) ? "default " + (typeEnum.isStringType() ? "'" + columnVO.getColumnDefault() + "'" : columnVO.getColumnDefault()) : "",
                columnVO.getRemark()
        );
        log.info("[修改数据库字段] 待执行字段修改sql:{}", sql);
        dbDao.executeDdl(sql);
    }

    /**
     * 新增字段
     *
     * @param columnVO
     */
    @Trace("新增字段")
    @Override
    public void addDbColumn(LcpDbColumnVO columnVO) {
        ELcpColumnTypeEnum typeEnum = ELcpColumnTypeEnum.of(columnVO.getDataType());
        String sql = String.format("alter table %s add column %s %s%s %s %s comment '%s' %s",
                columnVO.getTableName(),
                columnVO.getColumnName(),
                columnVO.getDataType(),
                columnVO.getLength() == null ? "" : "(" + columnVO.getLength() + ")",
                EYesOrNoEnum.YES.getCode().equals(columnVO.getNotNull()) ? "not null" : "",
                StringUtil.isNotBlank(columnVO.getColumnDefault()) ? "default " + (typeEnum.isStringType() ? "'" + columnVO.getColumnDefault() + "'" : columnVO.getColumnDefault()) : "",
                columnVO.getRemark(),
                StringUtil.isNotBlank(columnVO.getAfterColumn()) ? "after " + columnVO.getAfterColumn() : ""
        );
        log.info("[新增数据库字段] 待执行字段新增sql:{}", sql);
        dbDao.executeDdl(sql);
    }

    /**
     * 创建数据库表
     *
     * @param tableDetailVO
     */
    @Trace("创建数据库表")
    @Override
    public void createTable(LcpDbTableDetailVO tableDetailVO) {
        StringBuilder sb = new StringBuilder();
        sb.append("CREATE TABLE `").append(tableDetailVO.getTableName()).append("` (");
        Set<String> primaryColumns = new HashSet<>();
        List<LcpDbColumnVO> list = tableDetailVO.getColumnList();
        for (int i = 0; i < list.size(); i++) {
            LcpDbColumnVO columnVO = list.get(i);
            ELcpColumnTypeEnum typeEnum = ELcpColumnTypeEnum.of(columnVO.getDataType());
            sb.append(String.format("`%s` %s%s %s %s %s COMMENT '%s'"
                    , columnVO.getColumnName()
                    , columnVO.getDataType()
                    , columnVO.getLength() == null ? "" : "(" + columnVO.getLength() + ")"
                    , EYesOrNoEnum.YES.getCode().equals(columnVO.getAutoIncrement()) ? "AUTO_INCREMENT" : ""
                    , EYesOrNoEnum.YES.getCode().equals(columnVO.getNotNull()) ? "not null" : ""
                    , StringUtil.isNotBlank(columnVO.getColumnDefault()) ? "default " + (typeEnum.isStringType() ? "'" + columnVO.getColumnDefault() + "'" : columnVO.getColumnDefault()) : ""
                    , columnVO.getRemark()
            ));
            sb.append(i < list.size() - 1 ? "," : "");
            // 主键字段
            if (Boolean.TRUE.equals(columnVO.getPrimaryKeyFlag())) {
                primaryColumns.add(columnVO.getColumnName());
            }
        }
        if (CollectionUtil.isNotEmpty(primaryColumns)) {
            sb.append(", PRIMARY KEY (")
                    .append(primaryColumns.stream().map(item -> "`" + item + "`").collect(Collectors.joining(",")))
                    .append(")");
        }
        sb.append(String.format(") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='%s'", tableDetailVO.getTableComment()));
        log.info("[创建数据库表] 待执行表创建sql:{}", sb);
        dbDao.executeDdl(sb.toString());
    }
}
